<?php
/**
 * @name /lib/private/Notification.php
 * @author Mohammad Shabbir Hasan <shabbir_cse03@yahoo.com>
 * @author Michael Foss <michael@mikefoss.com>
 * @version 2011.04.04
 * 
 * A notification class to manage notifications.
 */

/**
 * Notification class.
 *
 */
class Notification {
  /**
   * Notification identification.
   *
   * @var integer
   */
  var $NotificationId;
  /**
   * Notification Status.
   *
   * @var integer
   */
  var $IsRead;
  /**
   * Subject of Notification.
   *
   * @var string
   */
  var $Subject;
  /**
   * Notification Message.
   *
   * @var string
   */
  var $Message;
  /**
   * Date of Notification.
   *
   * @var string
   */
  var $NotificationDate;
    
  /**
  *
  * Constructor.
  *
  */ 
  function Notification(){
  	$this->NotificationId = 0;
    $this->IsRead = 0;
    $this->Subject = '';
    $this->Message = '';
    $this->NotificationDate = 0;
  }
 
  /**
   * Gets a subset of notifications, sorted by notification id,
   * with an optional offset & maximum amount,
   * and an optional read status.
   *
   * @param integer
   * @param integer
   * @param boolean
   * @return Notification[]
   */
  function GetNotifications($offset = 0, $maxResults = 0, $isRead = null) {
    $objects = array();
    $db = new DB();
    // Initial query
    $query = "SELECT n.NotificationId FROM notifications n ";
    if ($isRead === true)
      $query .= "WHERE n.IsRead='1' ";
    elseif ($isRead === false)
      $query .= "WHERE n.IsRead='0' ";
    $query .= "ORDER BY n.NotificationId DESC";
    // Look for max results and offsets
    if ($maxResults && $maxResults * 1 == $maxResults) {
      $query .= " LIMIT $maxResults";
      if ($offset && $offset * 1 == $offset)
        $query .= " OFFSET $offset";
    }
    elseif ($offset && $offset * 1 == $offset)
      $query .= " LIMIT 99999999 OFFSET $offset";
    // Get the ids
    $ids = $db->QueryCol($query);
    // If we have ids, load the objects
    if (is_array($ids))
      foreach ($ids as $id) {
        $objects[count($objects)] = new Notification();
        $objects[count($objects) - 1]->Load($id);
      }
    return $objects;
  }

  /**
   * Determines if a notification exists or not.
   * 
   * @param integer
   * @return boolean
   */
  function Exists($notificationId) {
    $db = new DB();
    $sql = "SELECT n.NotificationId FROM notifications n WHERE n.NotificationId='" . addslashes($notificationId) . "' LIMIT 1;";
    return ($db->QueryVal($sql) > 0);
  }
  
  /**
   * Returns a string representation of the object.
   * 
   * @param string
   * @return string
   */
  function ToString($delimiter = "<br />") {
    $s = "";
    $s .= "NotificationId: " . $this->NotificationId . $delimiter;
    $s .= "IsRead " . $this->IsRead . $delimiter;
    $s .= "Subject: " . $this->Subject . $delimiter;
    $s .= "Message: " . $this->Message . $delimiter;
    $s .= "NotificationDate: " . date('m/d/Y h:i:s', $this->NotificationDate) . $delimiter;
    return $s;
  }
  
  /**
   * Returns the JSON representation of the object.
   *
   * @param bool
   * @return string
   */
  function ToJSON($forHTML = false) {
    $subject = str_replace("'", "\\'", $this->Subject);
    if ($forHTML)
      $subject = htmlspecialchars($subject);
    $message = str_replace("'", "\\'", $this->Message);
    if ($forHTML)
      $message = htmlspecialchars($message);
    $notificationDate = str_replace("'", "\\'", date('m/d h:i:s', $this->NotificationDate));
    if ($forHTML)
      $notificationDate = htmlspecialchars($notificationDate);
    $s = "{";
    $s .= "'NotificationId':'" . $notification->NotificationId . "'";
    $s .= ",'IsRead':'" . ($notification->IsRead ? '1' : '0') . "'";
    $s .= ",'Subject':'$subject'";
    $s .= ",'Message':'$message'";
    $s .= ",'NotificationDate':'$notificationDate'";
    $s .= "}";
    return $s;
  }

  /**
   * Loads a Notification; returns true on success, false on failure.
   *
   * @param integer
   * @return boolean
   */
  function Load($notificationId) {
    $db = new DB();
    // Prevent SQL injection once to ease coding later
    $notificationId = addslashes($notificationId);
    // Select bulk of the data
    $query = <<<HEREDOC
      SELECT
        n.NotificationId,
        n.IsRead AS IsRead,
        n.Subject AS Subject,
        n.Message AS Message,
        UNIX_TIMESTAMP(n.NotificationDate) AS NotificationDate
      FROM
        notifications n
      WHERE
        n.NotificationId='{$notificationId}'
HEREDOC;
    $data = $db->QueryRow($query);
    // If we can't find it, we can't load it
    if (!$data)
      return false;
    // Assign response
    $this->NotificationId = $data['NotificationId'];
    $this->IsRead = ($data['IsRead'] == '1' ? true : false);
    $this->Subject = $data['Subject'];
    $this->Message = $data['Message'];
    $this->NotificationDate = $data['NotificationDate'];

    // If we made it this far, we've loaded the object
    return true;
  }
  
  /**
   * Creates a notification;
   * returns true on success, false on failure.
   * 
   * @param string
   * @param string
   * @return boolean
   */
  function Create($subject = '', $message = '') {

    if (!$subject)
      $subject = 'No Subject';
    if (!$message)
      $message = 'No Message';
    $db = new DB();
    
    // Create a new notification record
    
    $sql = "INSERT INTO notifications (Subject, Message, NotificationDate) VALUES ('" . addslashes($subject) . "', '" . addslashes($message) . "', NOW());";
    $db->Query($sql);
    // Assign the newly-created id
    $sql = "SELECT LAST_INSERT_ID();";
    $this->NotificationId = $db->QueryVal($sql);
    $this->Subject = $subject;
    $this->Message = $message;

    // Verify the rest of the object data
    // if we can't, remove the data and fail out of the Create
    if (!$this->Save()) {
      Notification::Delete($this->NotificationId);
      $this->NotificationId = 0;
	  
      return false;
    }
    else
      return true;
  }

  /**
   * Saves a PRE-EXISTING Notificaion; returns true on success, false on failure.
   *
   * @return boolean
   */
  function Save() {
    // "Fix" the data
    $this->IsRead = trim($this->IsRead);
    $this->Subject = trim($this->Subject);
    $this->Message = trim($this->Message);
    $this->NotificationDate = trim($this->NotificationDate);

    // Make sure the notification exists
    if (!Notification::Exists($this->NotificationId))
      return false;
    $db = new DB();
    // Save the core notification data
    $sql =
      "UPDATE notifications SET " .
        "IsRead='" . addslashes($this->IsRead) . "', " .
        "Subject='" . addslashes($this->Subject) . "', " .		
        "Message='" . addslashes($this->Message) . "', " .
        "NotificationDate=NOW() " .		
      "WHERE " .
        "NotificationId='" . addslashes($this->NotificationId) . "';";
    $db->Query($sql);

    // Yay! We did it!
    return true;
  }

  /**
   * Deletes a notification; returns true on success, false on failure.
   *
   * @static
   * @param integer
   * @return boolean
   */
  function Delete($notificationId) {
    if (!Notification::Exists($notificationId))
      return false;
    $db = new DB();
    $db->Query("DELETE FROM notifications WHERE NotificationId='" . addslashes($notificationId) . "';");
    return true;
  }
  
  /**
   * Displays a notification widget; uses /www/notification-widget-ajax.php.
   *
   * @static
   */
  function DisplayWidget() {
    ?>
<div class="NotificationsWidget">
  <table class="display" cellpadding="5" cellspacing="0" border="1">
    <thead>
      <tr>
        <th>Delete</th>
        <th>Date</th>
        <th>Subject</th>
      </tr>
    </thead>
    <tbody>
<?
    foreach (Notification::GetNotifications() as $n) {
      $n->NotificationDate = date('n/j g:iA', $n->NotificationDate);
?>
      <tr class="<?=$n->IsRead ? 'Read' : 'Unread' ?>">
        <td><a class="Delete"></a><input type="hidden" class="NotificationId" value="<?=htmlspecialchars($n->NotificationId) ?>" /></td>
        <td class="Date"><?=htmlspecialchars($n->NotificationDate) ?></td>
        <td class="Subject"><?=htmlspecialchars($n->Subject) ?></td>
      </tr>
<?
    }
?>
    </tbody>
  </table>
  <div class="NotificationDialog">
    <label>Subject:</label><div class="Subject"></div>
    <label>Date:</label><div class="Date"></div>
    <hr style="clear: left;" /><br /><div class="Message"></div>
  </div>
</div>
<script type="text/javascript">
  $(function() {
    // Get the widget
    var $n = $('.NotificationsWidget table');
    // Get the notification dialog
    var $nd = $('.NotificationsWidget .NotificationDialog');
    // Closure used when deleting from dialog
    var $deleteButton;
    // Dialogize the dialog
    $nd.dialog({
      autoOpen: false,
      modal: true,
      width: 400,
      buttons: [
        {
          text: 'Delete',
          click: function() {
            $deleteButton.click();
            $(this).dialog('close');
          }
        },
        {
          text: 'OK',
          click: function() {
            $(this).dialog('close');
          }
        }
      ]
    });
    // Draw the table
    $n.dataTable({
      bJQueryUI: true,
      aaSorting: [
        [1, 'desc']
      ],
      aoColumns: [
        null,
        {
          sType: 'date'
        },
        null
      ],
      sPaginationType: 'full_numbers'
    });
    // Wire the delete button to..umm..delete
    $n.find('.Delete')
      .button({
        icons: {
          primary: 'ui-icon-trash'
        },
        label: 'Delete'
      })
      .click(function() {
        var $tr = $(this).closest('tr');
        $.post(
          '<?=_webroot('/notification-widget-ajax.php') ?>',
          {
            'Action': 'Delete',
            'NotificationId': $tr.find('input.NotificationId').val()
          },
          function() {
            $n.fnDeleteRow($tr[0]);
          }
        );
      });
    // Wire the rest of the stuff to open
    $n.find('td.Subject, td.Date')
      .click(function() {
        var $tr = $(this).closest('tr');
        console.log($nd);
        $deleteButton = $tr.find('input.Delete');
        $.post(
          '<?=_webroot('/notification-widget-ajax.php') ?>',
          {
            'Action': 'Open',
            'NotificationId': $tr.find('input.NotificationId').val()
          },
          function(notification) {
            $nd.find('.Subject').text(notification.Subject);
            $nd.find('.Date').text(notification.NotificationDate);
            $nd.find('.Message').html(notification.Message);
            $tr
              .removeClass('Unread')
              .addClass('Read');
            $nd.dialog('open');
          },
          'json'
        );
      });
  });
</script>
<?
  }
}
